home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / sw / sound.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  8.1 KB  |  309 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include "sw.h"
  18. #include "extern.h"
  19. #include "sound.h"
  20. #include "control.h"
  21. #include <stdio.h>
  22. #include <stream.h>
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <fcntl.h>
  26. #include <string.h>
  27. #include <audio.h>
  28. #include <audiofile.h>
  29.  
  30. #define    SAMPLERATE    16000
  31. #define    SAMPSPERSEC    (SAMPLERATE * 2)
  32.  
  33. static int        audioAvailable = FALSE;
  34. static ALport        audioPort;
  35. static ALconfig        audioConfig;
  36. static long        oldOutputRate;
  37. static short*        soundSamples[LastSound];
  38. static long        soundNumSamples[LastSound];
  39. static short*        soundBuffer;
  40. static long        lastSamplesLeft;
  41. static long        bufferFullSize, bufferHalfSize;
  42. static long        headSample, tailSample;
  43. static int        playedExplosion;
  44. static float        explosionVolume;
  45. static long        seekingSamplesLeft;
  46.  
  47. extern int        isPaused();
  48.  
  49. static int        readSound(Sound s, const char* dir, const char* name)
  50. {
  51.   soundSamples[int(s)] = NULL;
  52.   soundNumSamples[int(s)] = 0;
  53.  
  54.   // make file name
  55.   char fn[256];
  56.   sprintf(fn, "%s/%s", dir, name);
  57.  
  58.   // open file
  59.   int fd = open(fn, O_RDONLY);
  60.   if (fd < 0) {
  61.     cerr << fn << ": can't open file\n";
  62.     return FALSE;
  63.   }
  64.  
  65.   // check format
  66.   switch (AFidentifyfd(fd)) {
  67.     case AF_FILE_AIFFC:
  68.     case AF_FILE_AIFF:
  69.     break;
  70.     default:
  71.     cerr << fn << ": not AIFF or AIFF-C\n";
  72.     return FALSE;
  73.   }
  74.  
  75.   // open file
  76.   AFfilehandle f = AFopenfd(fd, "r", AF_NULL_FILESETUP);
  77.   if (f == AF_NULL_FILEHANDLE) {
  78.     cerr << fn << ": can't open file\n";
  79.     return FALSE;
  80.   }
  81.  
  82.   // check that it's the right type
  83.   if (AFgetchannels(f, AF_DEFAULT_TRACK) != 2) {
  84.     cerr << fn << ": wrong number of channels (!=2)\n";
  85.     AFclosefile(f);
  86.     return FALSE;
  87.   }
  88.   long fmt, width;
  89.   AFgetsampfmt(f, AF_DEFAULT_TRACK, &fmt, &width);
  90.   if (width != 16) {
  91.     cerr << fn << ": wrong resolution (!=16 bits/sample)\n";
  92.     AFclosefile(f);
  93.     return FALSE;
  94.   }
  95.  
  96.   // find length of sound and make buffer
  97.   long frames = AFgetframecnt(f, AF_DEFAULT_TRACK) * 2;
  98.   soundSamples[int(s)] = new short[frames * 2];
  99.  
  100.   // read sound into buffer
  101.   frames = AFreadframes(f, AF_DEFAULT_TRACK, soundSamples[int(s)], frames);
  102.   soundNumSamples[int(s)] = frames * 2;
  103.  
  104.   // quiet down the sound
  105.   for (long i = 0; i < soundNumSamples[int(s)]; i++)
  106.     soundSamples[int(s)][i] >>= 2;
  107.  
  108.   // close file
  109.   AFclosefile(f);
  110.  
  111.   return TRUE;
  112. }
  113.  
  114. static void        deleteSounds()
  115. {
  116.   for (int i = 0; i < int(LastSound); i++)
  117.     delete[] soundSamples[i];
  118. }
  119.  
  120. int            openSound(const char* dir)
  121. {
  122.   if (ALqueryparams(AL_DEFAULT_DEVICE, NULL, 0) == 0)
  123.     return FALSE;
  124.  
  125.   // get old sampling rate
  126.   long outRateBuf[2];
  127.   outRateBuf[0] = AL_OUTPUT_RATE;
  128.   ALgetparams(AL_DEFAULT_DEVICE, outRateBuf, 2);
  129.   oldOutputRate = outRateBuf[1];
  130.  
  131.   // set new sampling rate
  132.   outRateBuf[0] = AL_OUTPUT_RATE;
  133.   outRateBuf[1] = SAMPLERATE;
  134.   ALsetparams(AL_DEFAULT_DEVICE, outRateBuf, 2);
  135.  
  136.   // read in audio files
  137.   readSound(ExplosionSound, dir, "explosion.aiff");
  138.   readSound(KilledSound, dir, "killed.aiff");
  139.   readSound(SeekingSound, dir, "seeking.aiff");
  140.   readSound(LockOnSound, dir, "lockon.aiff");
  141.   readSound(GrabSound, dir, "grab.aiff");
  142.   readSound(DropSound, dir, "drop.aiff");
  143.   readSound(EnemyGrabSound, dir, "flag_alert.aiff");
  144.   readSound(FlagWonSound, dir, "flag_won.aiff");
  145.   readSound(FlagLostSound, dir, "flag_lost.aiff");
  146.   readSound(MissileSound, dir, "missile.aiff");
  147.   readSound(LaserSound, dir, "laser.aiff");
  148.  
  149.   // find longest sound
  150.   bufferHalfSize = 0;
  151.   for (int i = 0; i < int(LastSound); i++)
  152.     if (soundNumSamples[i] > bufferHalfSize)
  153.       bufferHalfSize = soundNumSamples[i];
  154.   bufferFullSize = 2 * bufferHalfSize;
  155.  
  156.   // make local buffer for adding up sounds
  157.   soundBuffer = new short[bufferFullSize];
  158.   if (!soundBuffer) {
  159.     deleteSounds();
  160.     return FALSE;
  161.   }
  162.  
  163.   // configure port
  164.   audioConfig = ALnewconfig();
  165.   ALsetqueuesize(audioConfig, 2 * SAMPSPERSEC * 2);
  166.   ALsetwidth(audioConfig, AL_SAMPLE_16);
  167.   ALsetchannels(audioConfig, AL_STEREO);
  168.  
  169.   // open port
  170.   audioPort = ALopenport("swport", "w", audioConfig);
  171.   if (!audioPort) {                // can't open port
  172.     delete[] soundBuffer;
  173.     deleteSounds();
  174.     ALfreeconfig(audioConfig);
  175.     return FALSE;
  176.   }
  177.  
  178.   soundReset();
  179.   audioAvailable = TRUE;
  180.   return TRUE;
  181. }
  182.  
  183. void            closeSound()
  184. {
  185.   if (!audioAvailable) return;
  186.  
  187.   // close port
  188.   ALcloseport(audioPort);
  189.  
  190.   // free configuration
  191.   ALfreeconfig(audioConfig);
  192.  
  193.   // set back to old sampling rate
  194.   long outRateBuf[2];
  195.   outRateBuf[0] = AL_OUTPUT_RATE;
  196.   outRateBuf[1] = oldOutputRate;
  197.   ALsetparams(AL_DEFAULT_DEVICE, outRateBuf, 2);
  198.  
  199.   // free sample buffers
  200.   delete[] soundBuffer;
  201.   deleteSounds();
  202.  
  203.   // can't play sounds anymore
  204.   audioAvailable = FALSE;
  205. }
  206.  
  207. int            hasSound()
  208. {
  209.   return audioAvailable;
  210. }
  211.  
  212. void            soundReset()
  213. {
  214.   headSample = 0;
  215.   tailSample = headSample;
  216.   lastSamplesLeft = 0;
  217.   seekingSamplesLeft = 0;
  218.   playedExplosion = FALSE;
  219. }
  220.  
  221. void            soundAdvance(float dt)
  222. {
  223.   if (!audioAvailable) return;            // no audio
  224.   if (headSample == tailSample) return;        // nothing to play
  225.  
  226.   // find how many samples left in port
  227.   long samplesLeft = ALgetfilled(audioPort);
  228.   if (samplesLeft > long(1.25*dt*SAMPSPERSEC))
  229.     return;                    // not empty enough yet
  230.  
  231.   // write more samples and move fill point
  232.   long samplesUsed = lastSamplesLeft - samplesLeft;
  233.   long samplesPlay = long(2.5*dt*SAMPSPERSEC) & ~1;
  234.   if (samplesPlay > ALgetfillable(audioPort)) {    // will block
  235.     soundReset();                //  just give up and start over
  236.   }
  237.   else if (samplesPlay > tailSample-headSample) { // will empty local buffer
  238.     samplesPlay = tailSample - headSample;
  239.     ALwritesamps(audioPort, soundBuffer + headSample, samplesPlay);
  240.     headSample = tailSample = 0;
  241.     seekingSamplesLeft = 0;
  242.   }
  243.   else {
  244.     ALwritesamps(audioPort, soundBuffer + headSample, samplesPlay);
  245.     // if past mid-point of local buffer, shift samples to beginning of buffer
  246.     if ((headSample += samplesPlay) >= bufferHalfSize) {
  247.       memmove(soundBuffer, soundBuffer + headSample,
  248.                     int(tailSample - headSample));
  249.       tailSample -= headSample;
  250.       headSample = 0;
  251.     }
  252.   }
  253.   lastSamplesLeft = samplesLeft + samplesPlay;
  254.  
  255.   // update local flags
  256.   playedExplosion = FALSE;
  257.   if ((seekingSamplesLeft -= samplesUsed) < 0)
  258.     seekingSamplesLeft = 0;
  259. }
  260.  
  261. void            soundPlay(Sound s, float volume)
  262. {
  263.   if (!audioAvailable) return;
  264.   if (isPaused()) return;
  265.   if (soundDial() == SoundOff) return;
  266.   if (soundDial() == SoundWarnings &&
  267.         (s == ExplosionSound ||
  268.          s == KilledSound ||
  269.          s == GrabSound ||
  270.          s == DropSound ||
  271.          s == FlagWonSound ||
  272.          s == FlagLostSound))
  273.     return;
  274.   if (soundNumSamples[int(s)] == 0) return;    // empty sound
  275.  
  276.   if (s == ExplosionSound) {
  277.     // limit the number of explosions played simultaneously
  278.     if (playedExplosion && volume < 2.0*explosionVolume) return;
  279.     playedExplosion = TRUE;
  280.     explosionVolume = volume;
  281.   }
  282.   else if (s == SeekingSound) {
  283.     // play seeking repeatedly (but not on top of itself)
  284.     if (seekingSamplesLeft > 0) return;
  285.     seekingSamplesLeft += soundNumSamples[int(s)];
  286.   }
  287.  
  288.   long c = soundNumSamples[int(s)];
  289.   short* b = soundSamples[int(s)];
  290.   short *sp = soundBuffer + headSample;
  291.  
  292.   // clear out any samples that we'll touch that haven't been touched yet
  293.   if (headSample + c > tailSample) {
  294.     long i = tailSample;
  295.     tailSample = headSample + c;
  296.     for (; i < tailSample; i++)
  297.       soundBuffer[i] = 0;
  298.   }
  299.  
  300.   if (volume == 1.0) {                // direct copy
  301.     for (long i = 0; i < c; i++)
  302.       *sp++ += *b++;
  303.   }
  304.   else {                    // scaled copy
  305.     for (long i = 0; i < c; i++)
  306.       *sp++ += short(volume * float(*b++));
  307.   }
  308. }
  309.